package email;

import java.io.*;
import java.util.*;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.Flags.Flag;
import javax.mail.search.SearchTerm;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import entity.CashFlow;
import entity.CashFlow.Period;
import exception.IllegalInput;
import graphicalUserInterface.NotifyPrompt;

import settings.MasterController;

//@author U096819H
public class ReceiveMail {
	Folder inbox;
	private String username;
	private String password;
	private String owner;
	private MasterController mc;

	// @author U096819H
	public ReceiveMail(String user, String pass, String checkForUser,
			MasterController _mc) {
		username = user;
		password = pass;
		owner = checkForUser;
		mc = _mc;
	}

	// @author U096819H
	public void checkMail() {
		Properties props = System.getProperties();
		props.setProperty("mail.store.protocol", "imaps");
		try {
			Session session = Session.getDefaultInstance(props, null);
			Store store = session.getStore("imaps");
			store.connect("imap.gmail.com", username, password);
			inbox = store.getFolder("Inbox");
			System.out.println("No of Unread Messages : "
					+ inbox.getUnreadMessageCount());
			inbox.open(Folder.READ_WRITE);
			SearchTerm searchCondition = new SearchTerm() {
				@Override
				public boolean match(Message message) {
					try {
						Address[] froms = message.getFrom();
						String email = froms == null ? null
								: ((InternetAddress) froms[0]).getAddress();
						if (email.equals(owner)
								&& !(message.getFlags().contains(Flag.SEEN))) {
							return true;
						}
					} catch (MessagingException ex) {
						ex.printStackTrace();
					}
					return false;
				}
			};
			Message messages[] = inbox.search(searchCondition);
			FetchProfile fp = new FetchProfile();
			fp.add(FetchProfile.Item.ENVELOPE);
			fp.add(FetchProfile.Item.CONTENT_INFO);
			inbox.fetch(messages, fp);

			try {
				parseAllMessages(messages);
				inbox.close(true);
				store.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}

	// @author U096819H
	private void parseAllMessages(Message[] msgs) throws Exception {
		for (int i = 0; i < msgs.length; i++) {
			System.out.println("MESSAGE #" + (i + 1) + ":");
			printEnvelope(msgs[i]);
		}
	}

	// @author U096819H
	private void printEnvelope(Message message) throws Exception {
		Address[] a;
		String subject = message.getSubject();
		Date receivedDate = message.getReceivedDate();
		String content = message.getContent().toString();
		getContent(message);
	}

	// @author U096819H
	private void getContent(Message msg) {
		try {
			String contentType = msg.getContentType();
			Multipart mp = (Multipart) msg.getContent();
			int count = mp.getCount();
			dumpPart(mp.getBodyPart(0));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	// @author U096819H
	private void dumpPart(Part p) throws Exception {
		// Dump input stream ..
		InputStream is = p.getInputStream();
		// If "is" is not already buffered, wrap a BufferedInputStream
		// around it.
		if (!(is instanceof BufferedInputStream)) {
			is = new BufferedInputStream(is);
		}

		byte[] contents = new byte[1024];
		int bytesRead = 0;
		String strFileContents = "";
		while ((bytesRead = is.read(contents)) != -1) {
			strFileContents = new String(contents, 0, bytesRead);
		}
		createExpense(strFileContents);
	}

	// @author U096819H
	private void createExpense(String content) {
		String regex = ":";
		String[] split = content.split(regex);
		String title = trimStringFront(split[0]);
		String amount = trimStringBack(split[1]);
		String category = "<e-mail>";
		String source = "<unallocated>";
		Calendar _date = Calendar.getInstance();
		try {
			mc.AddExpense(title, category, Double.parseDouble(amount), source,
					_date, false, null, "");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// @author U096819H
	private String trimStringFront(String content) {
		String regex = "\n";
		String[] split = content.split(regex);
		return split[split.length - 1];
	}

	// @author U096819H
	private String trimStringBack(String content) {
		String regex = " ";
		String[] split = content.split(regex);
		regex = "\n";
		split = split[0].split(regex);
		return split[0];
	}
}
